import os
import re
import time
import threading
from collections import defaultdict
import numpy as np
from loguru import logger
# from pympler import asizeof

dir = os.path.dirname(os.path.abspath(__file__))
log_dir = os.path.join(os.path.dirname(dir), "log", "logs")
if not os.path.exists(log_dir):
    os.makedirs(log_dir, exist_ok=True)
# 自定义日志格式
logger.remove()  # 移除默认的日志处理器
logger.add(
    sink=os.path.join(log_dir, "process_{time:YYYY-MM-DD}.log"),  # 日志文件名带日期
    format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level} | {function}:{line} - {message}",
    rotation="00:00",           # 每天午夜轮转（与大小轮转二选一）
    retention="360 days",       # 保留最近360天的日志
    encoding="utf-8",           # 避免中文乱码
    level="INFO",               # 文件日志级别
)


class RadarData:
    def __init__(self, device_info, speed_limit, density_limit, flow_limit, task_name, speed_flag=True):
        self.device_info = device_info
        # 区间限速与拥堵等级
        self.speed_limit = speed_limit
        self.density_limit = density_limit
        self.flow_limit = flow_limit
        self.task_name = task_name
        # 用于存储车辆信息
        self.vehicle_data = defaultdict(dict)
        # 直接使用雷达速度值
        self.speed_flag = speed_flag
        # 历史数据留存
        self.history_data = defaultdict(list)
        # 存储设备点位ID的数据列表
        self.device_list = []
        self.id_lane = defaultdict(list)
        self.device_heartbeat = defaultdict(int)
        self.device_flow_dict = defaultdict(list)
        self.current_time = int(time.time() * 1000)

    def check_departure_and_calculate_speed(self, n=5):
        departed_vehicles = {}
        flow_sn = {}
        try:
            delete_uuids = {}
            for key, value in self.vehicle_data.items():
                departed_vehicles[key] = []
                delete_uuids[key] = []
                for uuid, record in list(value.items()):
                    # time_diff = self.time_diff[key]
                    # 假设超过10秒未见则认为已离开
                    # current_time = int(time.time() * 1000) - time_diff
                    current_time = int(time.time() * 1000)
                    if current_time - record.get('last_seen', 0) > 10000:

                        # 筛选有真实行驶轨迹的车辆
                        if len(record['speed_list']) > 30:
                            # 排序
                            sorted_data = sorted(record['speed_list'])
                            # 去掉最小的n个和最大的n个
                            trimmed_data = sorted_data[n:-n]
                            # 计算均值
                            avg_speed = sum(trimmed_data) / len(trimmed_data)
                            departed_vehicles[key].append(avg_speed)
                        # 移除已离开的车辆记录
                        delete_uuids[key].append(uuid)
                while len(self.device_flow_dict[key]) > 0:
                    if self.device_flow_dict[key][0] < self.current_time - 3600000:
                        self.device_flow_dict[key].pop(0)
                    else:
                        break
                for key, time_list in self.device_flow_dict.items():
                    flow_sn[key] = len(time_list)

            # 统一删除已离开的车辆记录
            for key, uuids in delete_uuids.items():
                for uuid in uuids:
                    del self.vehicle_data[key][uuid]
        except Exception as e:
            logger.opt(exception=e).error(f"数据处理失败")

        return departed_vehicles, flow_sn

    def get_level(self, avg_speed, density, flow):
        # 1：中流量+无拥堵、2：中流量+拥堵、3：高流量+无拥堵、4：高流量+拥堵
        limit_speed = self.device_info["limit"]
        speed_limit = self.speed_limit[str(limit_speed)]
        if avg_speed > speed_limit['l2'] or density <= self.density_limit['l1'] or avg_speed == 0:
            level = 0
        else:
            level = 1

        lane_num = self.device_info["lane_num"]
        flow_limit = self.flow_limit[str(lane_num)]
        if flow < flow_limit['l1']:
            level = 0
        elif flow < flow_limit['l2']:
            if level == 0:
                level = 1
            else:
                level = 2
        else:
            if level == 0:
                level = 3
            else:
                level = 4

        return level

    def deal_kafka_message(self, message_data):
        try:
            if 'detectTimeStamp' not in message_data.keys():
                return
            if "e1FrameParticipant" not in message_data.keys():
                return
            if "siteCode" not in message_data.keys():
                return
            siteCode = message_data["siteCode"]
            if siteCode != self.task_name:
                return
            # 获取毫秒级时间戳
            timestamp = int(message_data["detectTimeStamp"])
            for vehicle in message_data["e1FrameParticipant"]:
                sn = vehicle["baseStationSource"]
                if not isinstance(sn, str):
                    sn = str(int(sn))
                if sn not in self.device_list:
                    self.device_list.append(sn)
                    self.vehicle_data[sn] = {}
                    self.device_flow_dict[sn] = []
                if "picLicense" not in vehicle.keys():
                    continue
                plate = vehicle["picLicense"].strip()
                if plate == "":
                    continue
                speed = vehicle["speed"]
                if plate not in self.vehicle_data[sn].keys():
                    self.device_flow_dict[sn].append(timestamp)
                    self.vehicle_data[sn][plate] = {
                        'entry_time': timestamp,
                        'last_seen': timestamp,
                        'speed_list': [speed]
                    }
                else:
                    self.vehicle_data[sn][plate]['last_seen'] = timestamp
                    self.vehicle_data[sn][plate]['speed_list'].append(speed)
        except Exception as e:
            logger.opt(exception=e).error(f"解析数据失败, data:{message_data}")

    def run(self, q_data, congestion_queue):
        # threading.Thread(target=self.threading_data).start()
        last_time = time.time()
        while True:
            time.sleep(0.001)
            try:
                # logger.info("开始处理数据")
                while not q_data.empty():
                    frame_data = q_data.get(block=True)
                    # logger.info(f"处理数据{frame_data}")
                    self.deal_kafka_message(frame_data)

                # 每30秒检查并输出平均速度
                self.current_time = int(time.time())
                if self.current_time % 30 == 0 and self.current_time - last_time >= 5:
                    last_time = self.current_time
                    put_dict = {}
                    sn_data_dict = {}
                    # 计算各点位车辆均速、小时流量
                    speeds_dict, flow_sn = self.check_departure_and_calculate_speed()
                    # 计算点位均速
                    for device_id, speeds in speeds_dict.items():
                        if speeds:
                            avg_speed = sum(speeds) / len(speeds)
                            avg_speed = round(avg_speed, 2)
                            density = len(list(self.vehicle_data[device_id].keys()))
                            # print(f"设备{device_id}平均速度{avg_speed}，密度{density}")
                            sn_data_dict[device_id].append([avg_speed, density])

                    for new_id, data in sn_data_dict.items():
                        if data:
                            new_speed = 0
                            new_density = 0
                            for avg_speed, density in data:
                                new_speed += avg_speed
                                new_density += density
                            if len(data) > 0:
                                new_avg_speed = new_speed / len(data)
                                new_avg_density = new_density / len(data)
                                # 小时流量
                                hour_flow = flow_sn[new_id]
                                level = self.get_level(new_avg_speed, new_avg_density, hour_flow)
                                self.history_data[new_id].append([time.time(), new_avg_speed, new_avg_density, hour_flow, level])
                                logger.info(
                                    f"history_data: time: {int(time.time())}, deviceId: {new_id}, data: {[new_avg_speed, new_avg_density, level]}")
                                if new_avg_density > 10 and level != 0:
                                    put_dict[new_id] = [new_id, new_avg_speed, new_avg_density, hour_flow, level]
                            else:
                                self.device_heartbeat[new_id] += 1
                                if len(self.history_data[new_id]) > 0:
                                    last = self.history_data[new_id][-1]
                                    self.history_data[new_id].append(last)
                                    if last[2] > 10 and last[4] != 0 and self.device_heartbeat[new_id] <= 10:
                                        put_dict[new_id] = [new_id, last[1], last[2], last[3], last[4]]

                    for device_id, data in put_dict.items():
                        if len(self.history_data[device_id]) > 10:
                            history_data = self.history_data[device_id][-2]
                            if history_data[4] != 0:
                                logger.info(f"time:{int(time.time())}, deviceId: {device_id}, data: {data}")
                                congestion_queue.put(data)
                    # 清除过期缓存
                    for device_id, data in self.history_data.items():
                        if len(data) > 100:
                            data.pop(0)
                    time.sleep(0.01)

            except Exception as e:
                logger.opt(exception=e).error(f"数据处理失败")